home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / math / gle-3.000 / gle-3 / gle / axis.c < prev    next >
C/C++ Source or Header  |  1995-02-07  |  13KB  |  510 lines

  1. #include "all.h"
  2.  
  3. #include "justify.h"
  4. #include "axis.h"
  5. #include <math.h>
  6. #include "mygraph.h"
  7. int start_subtick(double *tick1, double gmin, double dticks);
  8. int nice_ticks(double *dticks, double *gmin,double *gmax
  9.     , double *t1,double *tn,int minset, int maxset);
  10. int numtrim(char **d,char *s, double dticks);
  11.  
  12. int nice_log_ticks(double *start, double *last, double *gmin, double *gmax);
  13. double fnloglen(double v,struct axis_struct *ax);
  14. double fnlogx(double v,struct axis_struct *ax);
  15. int fnbig(double v);
  16.  
  17. /*
  18. #define fnx(vv)  (((vv-gmin)/(gmax-gmin)) * ax->length)
  19. */
  20. #define fnx(vv) m_fnx(vv)
  21. #define fnlx(vv) fnlogx(vv,ax)
  22. #define true (!false)
  23. #define false 0
  24. struct axis_struct ax;
  25.  
  26. #define kw(ss) if (strcmp(tok(ct),ss)==0)
  27.  
  28. static double  gglen,ggmin,ggmax,ggnegate;
  29. double m_fnx(double v);
  30. double m_fnx(double v)
  31. {
  32.     if (ggnegate)     {
  33.         v = ggmax - (v-ggmin);
  34.     }
  35.     return (((v-ggmin)/(ggmax-ggmin)) * gglen );
  36.  
  37. }
  38. draw_axis(struct axis_struct *ax)    /* Draws the axis */
  39. {
  40.     double fi,x,y,gmin,gmax,dticks,tick1,tickn;
  41.     int i,xax,n,savecap,dolittle;
  42.        int isbig;
  43.     double tlen,stlen,dsubticks,tt,t,start;
  44.     double h,label_width,dist;
  45.     double bl,br,bu,bd;
  46.     double ox,oy,llen,maxd,maxwid,ty,tx;
  47.     double th;
  48.  
  49.     if (ax->type==1 || ax->type==3) xax = true; else xax = false;
  50.     g_source("BEGIN AXIS  =====\n");
  51. /*! Return if side is turned OFF*/
  52.     if (ax->off) return ;
  53. #define dont if (1==2)
  54. /*! Ok lets draw the side first. */
  55.     g_get_line_cap(&savecap);
  56.     g_get_xy(&ox,&oy);
  57.     g_gsave();
  58.     g_set_color(ax->side_color);
  59.     g_set_line_width(ax->side_lwidth);
  60.     g_set_line_style(ax->side_lstyle);
  61.     if (!ax->side_off) {
  62.         g_set_line_cap(1);
  63.         g_get_xy(&x,&y);
  64.         if (xax)
  65.             g_line(x+ax->length,y);
  66.         else
  67.             g_line(x,y+ax->length);
  68.     }
  69.     g_grestore();
  70.     g_set_line_cap(savecap);
  71.  
  72. /*----------------------------- Generate the places for labels to go */
  73.     ggmin = ax->min;
  74.     ggmax = ax->max;
  75.     ggnegate = ax->negate;
  76.     gmin = ax->min;
  77.     gmax = ax->max;
  78.     gglen = ax->length;
  79.  
  80.     if (ax->log) {    /* generate places for log main ticks */
  81.      if (!ax->lgset) {
  82.         /* dist between 10^0 and 10^1 */
  83.         dist = fnloglen(2,ax) - fnloglen(1,ax);
  84.         if (dist > ax->base*4.5) ax->lg25 = true;
  85.         if (dist > ax->base*22.0) ax->lg1 = true;
  86.      }
  87.      nice_log_ticks(&tick1,&tickn,&gmin,&gmax);
  88.      if (ax->nplaces == 0) { /* haven't been set, so generate positions. */
  89.       for (fi=tick1; fi<= tickn+(pow(10.0,floor(log10(fi)+.0001)))/100
  90.             ; fi += pow(10.0,floor(log10(fi)+.0001))) {
  91.         i = floor(.0001 + fi/pow(10.0,floor(log10(fi))));
  92.         if (fnbig(fi) || (ax->lg1) || (ax->lg25 && ((i==2) || (i==5))) ) {
  93.          if (++(ax->nplaces)>199) {gprint("Too many places\n");return;}
  94.          ax->places[ax->nplaces] = fi;
  95.         }
  96.       }
  97.      }
  98.     } else {
  99.     dticks = 0;
  100.     if (ax->nticks!=0)  dticks = (gmax - gmin)/ax->nticks;
  101.     if (ax->dticks!=0)  dticks = ax->dticks ;
  102.     if (dticks>0) if ((gmax - gmin)/dticks>90) {gprint("too many ticks \n"); dticks = 0;}
  103.  
  104.     nice_ticks(&dticks, &gmin, &gmax, &tick1, &tickn,ax->minset,ax->maxset);
  105.  
  106.     if (ax->nofirst) tick1 = tick1 + dticks;
  107.     if (ax->nolast) tickn = tickn - dticks;
  108.     tickn = tickn + dticks/100; /* to avoid rounding errors */
  109.     if (ax->nplaces == 0) { /* haven't been set, so generate positions. */
  110.       { double end_tick = (tickn+dticks/100.0);
  111.       for (fi=tick1; fi<=end_tick; fi += dticks) {
  112.         if (++(ax->nplaces)>49) {gprint("Too many places\n");return;}
  113.         ax->places[ax->nplaces] = fi;
  114.       }
  115.       }
  116.     }
  117.     }
  118.  
  119. /*------------------------------  Now draw the ticks    (subticks first) */
  120.     g_gsave();
  121.  
  122.     tlen = ax->base/5;
  123.     if (ax->ticks_length!=0) tlen = ax->ticks_length;
  124.     /* first the subticks */
  125.     stlen = tlen/2;
  126.     if (ax->subticks_length!=0) stlen = ax->subticks_length;
  127.     dsubticks = 0;
  128.  
  129.     if (!ax->log) {    /* Draw little log ticks if enough space */
  130.     if (ax->nsubticks!=0)  dsubticks = (dticks)/(ax->nsubticks+1);
  131.     if (ax->dsubticks!=0)  dsubticks = ax->dsubticks;
  132.     if (dsubticks==0) dsubticks = dticks / 2.0;
  133.     if ((gmax - gmin)/dsubticks>2000) {gprint("too many subticks \n");
  134.                         dsubticks = dticks;}
  135.  
  136.     start_subtick(&tick1, gmin, dsubticks);
  137.     g_set_color(ax->subticks_color);
  138.     g_set_line_width(ax->subticks_lwidth);
  139.     g_set_line_style(ax->subticks_lstyle);
  140.     if (ax->type>2) t = -stlen; else t = stlen;
  141.     if (!ax->subticks_off) {
  142.       if (dsubticks==0) dsubticks = dticks / 2.0;
  143.       for (fi=tick1; fi<=gmax; fi += dsubticks) {
  144. /*         if (!fnbig(fi)) { */
  145.         if (xax) {
  146.             g_move(ox+fnx(fi),oy);
  147.             g_line(ox+fnx(fi),oy+t);
  148.         } else {
  149.             g_move(ox,fnx(fi)+oy);
  150.             g_line(ox+t,oy+fnx(fi));
  151.         }
  152. /*        }     */
  153.       }
  154.     }
  155.     }
  156.  
  157. /*------------------------------  Now the main ticks */
  158.     g_set_color(ax->ticks_color);
  159.     g_set_line_width(ax->ticks_lwidth);
  160.     g_set_line_style(ax->ticks_lstyle);
  161.  
  162.     if (ax->type>2) t = -tlen; else t = tlen;
  163.     if (ax->type>2) tt = -stlen; else tt = stlen;
  164.     if (!ax->ticks_off) {
  165.       if (ax->log) {    /* Draw log ticks */
  166.         g_set_color(ax->subticks_color);
  167.         g_set_line_width(ax->subticks_lwidth);
  168.         g_set_line_style(ax->subticks_lstyle);
  169.         nice_log_ticks(&tick1,&tickn,&gmin,&gmax);
  170.         for (fi=tick1; fi<= tickn+(pow(10.0,floor(log10(fi)+.0001)))/100
  171.             ; fi += pow(10.0,floor(log10(fi)+.0001))) {
  172.         i = floor(fi/pow(10.0,floor(log10(fi))));
  173.         isbig = (fnbig(fi));
  174.         if (isbig) {
  175.             x = t;
  176.                 g_set_color(ax->ticks_color);
  177.                 g_set_line_width(ax->ticks_lwidth);
  178.                 g_set_line_style(ax->ticks_lstyle);
  179.         } else x = tt;
  180.         if (xax) {
  181.             g_move(ox+fnlx(fi),oy);
  182.             g_line(ox+fnlx(fi),oy+x);
  183.         } else {
  184.             g_move(ox,fnlx(fi)+oy);
  185.             g_line(ox+x,oy+fnlx(fi));
  186.         }
  187.         if (isbig) {
  188.                 g_set_color(ax->subticks_color);
  189.                 g_set_line_width(ax->subticks_lwidth);
  190.                 g_set_line_style(ax->subticks_lstyle);
  191.         }
  192.         }
  193.       } else {
  194.         for (i=1;i<=ax->nplaces; i++) {
  195.         fi = ax->places[i];
  196.         if (xax) {
  197.             g_move(ox+fnx(fi),oy);
  198.             g_line(ox+fnx(fi),oy+t);
  199.         } else {
  200.             g_move(ox,fnx(fi)+oy);
  201.             g_line(ox+t,oy+fnx(fi));
  202.         }
  203.         }
  204.       }
  205.     }
  206.     g_grestore();
  207. /*------------------------------  Now draw the labels     */
  208.     llen = 0;
  209.     if (tlen<0) llen = -tlen;
  210.     h = ax->label_hei;
  211.     if (h==0) h = ax->base;
  212.     llen = llen + h*.5;
  213.     if (ax->label_dist!=0) llen = ax->label_dist;
  214.  
  215.     {char cbuff[100];
  216.     if (ax->nnam==0) {
  217.       if (ax->log) {
  218.         if (log10(gmax)-log10(gmin) < 5) dolittle = true;
  219.         else dolittle = false;
  220.         for (i=1;i<=ax->nplaces; i++) {
  221.         fi = ax->places[i];
  222.         n = floor(.0001 + fi/pow(10.0,floor(log10(fi))));
  223.         if (fnbig(fi)) {
  224.             n = floor(log10(fi)+.5);
  225.             sprintf(cbuff,"10\\sup {%d}",n);
  226.             mystrcpy(&ax->names[i],cbuff);
  227.         } else {
  228.           if (dolittle) {
  229.             n = floor(.0001 + fi/(pow(10.0,floor(log10(fi)))));
  230.             sprintf(cbuff,"{\\sethei{%g}%d}",h*.7,n);
  231.             mystrcpy(&ax->names[i],cbuff);
  232.           }
  233.         }
  234.         }
  235.         ax->nnam = ax->nplaces;
  236.       } else {
  237.         for (i=1;i<=ax->nplaces; i++) {
  238.         fi = ax->places[i];
  239.         x = fabs(fi);
  240.         if (x<.00001*dticks) {fi = 0; x = 0;}
  241.         if (ax->decimal>0) {
  242.             sprintf(cbuff,"%.*f",ax->decimal,fi);
  243.             ax->names[i] = myallocz(20);
  244.             strncpy(ax->names[i],cbuff,19);
  245.         } else {
  246.             if (fi==0 || (x>1e-5 && x<1e6)) sprintf(cbuff,"%f",fi);
  247.             else sprintf(cbuff,"%e",fi);
  248.             numtrim(&ax->names[i],cbuff,dticks);
  249.         }
  250.         }
  251.         ax->nnam = ax->nplaces;
  252.       }
  253.     }}
  254.     g_set_color(ax->label_color);
  255.     g_set_line_width(ax->label_lwidth);
  256.     g_set_line_style(ax->label_lstyle);
  257.     g_set_font(ax->label_font);
  258.     g_set_hei(h);
  259.     maxd = 0;
  260.     maxwid = 0;
  261.     tx = ox-.3*h;   /* I wonder what tx should be set to ??? */
  262.      if (ax->type==4) tx = ox + .3*h;
  263.     if (ax->type==1) ty = oy-llen-.3*h;
  264.     if (ax->type==3) ty = oy+llen;
  265.     if (!ax->label_off) {
  266.       for (i=1;i<=ax->nnam;i++) {
  267.         g_measure(ax->names[i],&bl,&br,&bu,&bd);
  268.         if (bd>maxd) maxd = bd;
  269.         if (bl+br>maxwid) maxwid = bl+br;
  270.       }
  271.       for (i=1;i<=ax->nnam;i++) {
  272.         g_measure(ax->names[i], &bl, &br,&bu,&bd);
  273.         fi = fnx(ax->places[i]);
  274.         if (ax->log) fi = fnlx(ax->places[i]);
  275.         switch (ax->type) {
  276.           case 1: /* xaxis */
  277.             y = oy-llen-bu+bd-.3*h;
  278.             if (y<ty) ty = y;
  279.             g_move(ox+fi+ax->shift,oy-llen-(.7*h) );
  280.             g_jtext(JUST_CENTRE);
  281.             break;
  282.           case 2: /* yaxis */
  283.             x = ox-br+bl-llen-.3*h;
  284. /* bug here with axis labels 0 10 20, nofirst  */
  285.             if (i!=1 && i!=ax->nnam) if (x<tx) tx = x;
  286.             g_move(ox -llen ,oy+fi+ax->shift);
  287.             g_jtext(JUST_RC);
  288.             break;
  289.           case 3: /* x2axis */
  290.             y = oy+llen+maxd+bu;
  291.             if (y>ty) ty = y;
  292.             g_move(ox+fi+ax->shift,oy+llen+maxd);
  293.             g_jtext(JUST_CENTRE);
  294.             break;
  295.           case 4: /* y2axis */
  296.             x = ox+br-bl+llen+.3*h;
  297.             if (i!=1 && i!=ax->nnam) if (x>tx) tx = x;
  298.             g_move(ox+llen ,oy + fi +ax->shift);
  299.             g_jtext(JUST_LC);
  300.             break;
  301.         }
  302.         if (bd>maxd) maxd = bd;
  303.         if (bl+br>maxwid) maxwid = bl+br;
  304.       }
  305.     }
  306. /*---------------------------------- Now the axis title. */
  307.  
  308.     if (ax->title==NULL) return;
  309.     g_gsave();
  310.     th = h * 1.3;
  311.     if (ax->title_scale!=0) th = th*ax->title_scale ;
  312.     if (ax->title_hei!=0) th = ax->title_hei ;
  313.     g_set_color(ax->title_color);
  314.     g_set_font(ax->title_font);
  315.     g_set_hei(th);
  316.     g_measure(ax->title,&bl,&br,&bu,&bd);
  317.     if (!ax->title_off) {
  318.       switch (ax->type) {
  319.         case 1: /*  xaxis   */
  320.         g_move(ox+ax->length/2,ty - ax->title_dist);
  321.         g_jtext(JUST_TC);
  322.         break;
  323.         case 2: /*  yaxis   */
  324.         g_move(tx - ax->title_dist,oy + ax->length/2);
  325.         g_rotate(90.0);
  326.         g_jtext(JUST_BC);
  327.         g_rotate(-90.0);
  328.         break;
  329.         case 3: /*  x2axis   */
  330.         g_move(ox+ax->length/2,ty + ax->title_dist);
  331.         g_jtext(JUST_BC);
  332.         break;
  333.         case 4: /*  y2axis   */
  334.         g_move(tx + ax->title_dist,oy + ax->length/2);
  335.         if (ax->title_rot) {
  336.             g_rotate(-90.0);
  337.             g_jtext(JUST_BC);
  338.             g_rotate(90.0);
  339.         } else {
  340.             g_rotate(90.0);
  341.             g_jtext(JUST_TC);
  342.             g_rotate(-90.0);
  343.         }
  344.         break;
  345.       }
  346.     }
  347.     g_grestore();
  348.     g_move(ox,oy);
  349.     g_source("END AXIS  ===== \n");
  350. }
  351. /*-------------------------------------------------------------------------*/
  352. nice_ticks(double *dticks, double *gmin,double *gmax
  353.     , double *t1,double *tn,int minset, int maxset)
  354. {
  355.     double delta,st,expnt,n;
  356.     int ni;
  357.  
  358. /*      GMIN AND GMAX are set in GRAPH2.C in setrange()     */
  359.     delta = *gmax-*gmin;
  360.     if (delta==0) {gprint("Axis range error min=%g max=%g \n",*gmin,*gmax);
  361.         *gmax = *gmin+10;
  362.         delta = 10;
  363.     }
  364.     st = delta/10;
  365.     expnt = floor(log10(st));
  366.     n = st/pow(10.0,expnt);
  367.     if (n>5)
  368.         ni = 10;
  369.     else if (n>2)
  370.         ni = 5;
  371.     else if (n>1)
  372.         ni = 2;
  373.     else
  374.         ni = 1;
  375.     if (*dticks==0) *dticks = ni * pow(10.0,expnt);
  376.     if (*gmin - (delta/1000) <=  floor( *gmin/ *dticks) * *dticks)
  377.         *t1 = *gmin;
  378.     else
  379.         *t1 = (floor(*gmin/ *dticks) * *dticks ) + *dticks;
  380.  
  381.     *tn = *gmax;
  382. /*    gprint("tn %g,(%g) %g < %g \n",*tn,*gmax / *dticks,( floor( *gmax/ *dticks) * *dticks)
  383.             ,(*gmax - (delta/1000)) );
  384.  
  385. */
  386.     if (  (floor(.000001+ *gmax / *dticks) * *dticks) <
  387.       (*gmax - (delta/1000) ) )
  388.         *tn = floor(.00001 + *gmax/ *dticks ) * *dticks;
  389. /*
  390.     gprint("tn is now %g \n",*tn);
  391.     This is commented out because setting the range is different
  392.     from setting the labelling,  e.g. xaxis min 1 max 10.2 should not
  393.     label 10.2
  394.  
  395.     if (maxset) *tn = *gmax;
  396.     if (minset) *t1 = *gmin;
  397.     */
  398.  
  399. }
  400. /*-------------------------------------------------------------------------*/
  401. double chop(double f);
  402. double chop(double f)
  403. {
  404.     return (double) (int32) f;
  405. }
  406. /*-------------------------------------------------------------------------*/
  407. start_subtick(double *tick1, double gmin, double dticks)
  408. {
  409.     if (gmin == chop(gmin/dticks) * dticks)
  410.         *tick1 = gmin;
  411.     else
  412.         *tick1 = chop(gmin/dticks) * dticks + dticks;
  413. }
  414. /*-------------------------------------------------------------------------*/
  415. numtrime(char *o,char *s)
  416. {
  417.     char *nonzero;
  418.     char *e,*f;
  419.  
  420.     strcpy(o,s);
  421.  
  422.     e = strchr(s,'e');
  423.     if (e==NULL) return;
  424.  
  425.     e--;
  426.     for (; *e=='0'; e--) ;
  427.  
  428.     f = strchr(s,'e');
  429.     strcpy(e+1,f);
  430.     strcpy(o,s);
  431.  
  432. }
  433. /*-------------------------------------------------------------------------*/
  434. numtrim(char **d,char *s,double dticks)
  435. {
  436.     char *o,*nonzero=0;
  437.  
  438.     if (*d==0)  *d = myallocz(20);
  439.     o = *d;
  440.     nonzero = 0;
  441.     if (strchr(s,'e')!=NULL) {
  442.         numtrime(o,s);
  443.         return;
  444.     }
  445.     while (*s==' ' && *s!=0) s++;
  446.     while (*s!=0) {
  447.         *(o++) = *(s++);
  448.         if (*s=='.') {
  449.             nonzero = o-1;
  450.             if (dticks!=floor(dticks)) nonzero = o+1;
  451.             while (*s!=0) {
  452.                 *(o++) = *(s++);
  453.                 if ((*s!='0') && (*s!=0))
  454.                     if (o>nonzero) nonzero = o;
  455.             }
  456.         }
  457.     }
  458.     *(o++) = 0;
  459.     if (nonzero!=NULL) *(nonzero+1) = 0;
  460. }
  461. /*-------------------------------------------------------------------------*/
  462. nice_log_ticks(double *start, double *last, double *gmin, double *gmax)
  463. {
  464.     double sz;
  465.  
  466.     if (*gmin<=0) {
  467.         gprint("FATAL ERROR, LOG AXIS WITH MIN OF ZERO***\n");
  468.         *gmin = 1;
  469.     }
  470.     if (*gmax<=0) *gmax = 10;
  471.     *start = pow(10.0,floor(log10(*gmin)));
  472.  
  473.     if (floor(log10(*gmin)) != log10(*gmin)) {
  474.         sz = pow(10.0,floor(log10(*gmin)));
  475.         *start = floor((*gmin)/sz)*sz + sz;
  476.         if (*start>(*gmin+sz-sz/100)) *start = *start - sz;
  477.     }
  478.     *last = floor(log10(*gmax))+1;
  479.     if (floor(log10(*gmax))==log10(*gmax)) {
  480.         --*last;
  481.         *last = pow(10.0,*last);
  482.     } else {
  483.         *last = pow(10.0,*last-1);
  484.         *last = floor((*gmax) / *last) * *last;
  485.     }
  486. }
  487. double fnloglen(double v,struct axis_struct *ax)  /* Dist in cm in log axis */
  488. {
  489.     if (ax->negate) {
  490.         v = ax->max - (v- ax->min);
  491.     }
  492.    return ((v-log10(ax->min))/(log10(ax->max)-log10(ax->min))) * ax->length;
  493. }
  494. double fnlogx(double v,struct axis_struct *ax)
  495. {
  496.     if (ax->negate) {
  497.         v = ax->max - (v- ax->min);
  498.     }
  499.     return fnloglen(log10(v),ax);
  500. }
  501. fnbig(double v)
  502. {
  503.     if (fabs(log10(v)-floor(log10(v)+.5)) < .001)
  504.         return true;
  505.     else return false;
  506. }
  507.  
  508.  
  509.  
  510.